home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gawk / gawk213b.zoo / test / awf / pass1 < prev    next >
Encoding:
Text File  |  1991-04-20  |  5.4 KB  |  216 lines

  1. # first pass:  macro expansion and .if
  2. # We support macros, conditionals (of three quite limited forms), and macro
  3. # argument substitution.
  4. BEGIN {
  5.     curmacro = ""
  6.     macros[""] = 0        # just to make it an array
  7.     macrolen[""] = 0    # just to make it an array
  8.     macrotext[0] = ""    # just to make it an array
  9.     args[""] = ""        # just to make it an array
  10.     ntext = 1        # first slot in macrotext; cannot be 0
  11.     nroffset = 0        # offset between NR and "real" line numbers
  12.     inname = "?"        # input filename
  13.     sp = 0            # stack "pointer" (number of stacked macros)
  14.     maxsp = 25        # limit on nesting depth
  15.     macrostack[sp] = ""    # to make it an array
  16.     nleftstack[sp] = ""    # to make it an array
  17.     ptrstack[sp] = ""    # to make it an array
  18.     nargstack[sp] = ""    # to make it an array
  19.     argstack[sp] = ""    # to make it an array
  20.     condstack[sp] = ""    # to make it an array
  21. }
  22. /^\.\^#/ {            # filename and line no of next line: .^# no fn
  23.     nroffset = (NR+1) - $2
  24.     inname = $3
  25.     print
  26.     next
  27. }
  28. /^\.de/ {            # macro start
  29.     curmacro = "." $2
  30.     macros[curmacro] = ntext
  31.     macrostart = ntext
  32.     next
  33. }
  34. curmacro != "" && $0 !~ /^\.\.$/ {    # macro text - \\ becomes \
  35.     if ($0 !~ /\\/)        # quick case, no backslashes
  36.         line = $0
  37.     else {
  38.         line = ""
  39.         for (n = 1; n <= length; n++) {
  40.             if (substr($0, n, 2) == "\\\\")
  41.                 n++
  42.             line = line substr($0, n, 1)
  43.         }
  44.     }
  45.     macrotext[ntext++] = line
  46.     next
  47. }
  48. curmacro != "" && $0 ~ /^\.\.$/ {    # macro end
  49.     macrolen[curmacro] = ntext - macrostart
  50.     curmacro = ""
  51.     print ".^#", NR - nroffset + 1, inname
  52. #    print ".^#", int(NR - nroffset + 1), inname
  53.     next
  54. }
  55. $0 ~ /^\./ && ( macros[$1] != 0 || $0 ~ /^\.(i[ef]|el)/ ) {
  56.     # something that needs attention
  57.     print ".^=", NR - nroffset, inname
  58. #    print ".^=", int(NR - nroffset), inname
  59.     line = $0
  60.     nleft = 0
  61.     macro = "<none>"
  62.     nargs = 0
  63.  
  64.     while (line != "") {
  65.         # conditionals; note that 1-n is !n (awk doesn't have !)
  66.         invert = 0
  67.         if (line ~ /^\.i[ef] !/)
  68.             invert = 1
  69.         prevcond = cond
  70.         cond = 0
  71.         if (line !~ /^\.(i[ef]|el)/) {        # not conditional
  72.             cond = 1
  73.             iflen = 0
  74.         } else if (line ~ /^\.i[ef] !?\\n\(\.\$[<=>][0-9] /) {
  75.             # arithmetic comparison on arg count
  76.             iflen = length(".if .n(.$=x ") + invert
  77.             n = substr(line, iflen-1, 1) + 0
  78.             op = substr(line, iflen-2, 1)
  79.             if (op == "=" && nargs == n)
  80.                 cond = 1
  81.             else if (op == "<" && nargs < n)
  82.                 cond = 1
  83.             else if (op == ">" && nargs > n)
  84.                 cond = 1
  85.         } else if (line ~ /^\.i[ef] !?'\\\$[0-9]'[^']*' /) {
  86.             # string equality on argument
  87.             iflen = length(".if '.$n'") + invert
  88.             n = substr(line, iflen-1, 1)+0
  89.             if (n <= nargs)
  90.                 s1 = args[n]
  91.             else
  92.                 s1 = ""
  93.             i = index(substr(line, iflen+1), "'")
  94.             s2 = substr(line, iflen+1, i-1)
  95.             iflen += i+1
  96.             if (s1 == s2)
  97.                 cond = 1
  98.         } else if (line ~ /^\.i[ef] !?[nt] /) {
  99.             # nroff vs troff
  100.             iflen = length(".if n ") + invert
  101.             if (substr(line, iflen-1, 1) == "n")
  102.                 cond = 1
  103.         } else if (line ~ /^\.el /) {
  104.             cond = 1 - prevcond
  105.             iflen = length(".el ")
  106.         } else {
  107.             line = ".tm unknown .if/.ie form: " line
  108.             cond = 1
  109.             iflen = 0
  110.         }
  111.         if (invert)
  112.             cond = 1 - cond
  113.         if (cond && iflen > 0)        # trim true conditional off
  114.             line = substr(line, iflen+1)
  115.  
  116.         # do argument substitution, if necessary
  117.         if (cond && line ~ /\\\$/) {
  118.             orig = line
  119.             line = ""
  120.             for (pos = index(orig, "\\$"); pos > 0; \
  121.                         pos = index(orig, "\\$")) {
  122.                 if (pos > 1)
  123.                     line = line substr(orig, 1, pos-1)
  124.                 c = substr(orig, pos+2, 1)
  125.                 if (c ~ /[0-9]/ && c+0 <= nargs)
  126.                     line = line args[c+0]
  127.                 orig = substr(orig, pos+3)
  128.             }
  129.             line = line orig    # the remnant
  130.         }
  131.  
  132.         # is it an nroff command?
  133.         if (cond && line ~ /^\./) {
  134.             cmd = substr(line, 1, 3)
  135.             while (cmd ~ / $/)
  136.                 cmd = substr(cmd, 1, length(cmd)-1)
  137.         } else
  138.             cmd = ""
  139.  
  140.         # deal with it
  141.         if (!cond)
  142.             nop = 0        # nothing
  143.         else if (cmd == "" || macros[cmd] == 0)
  144.             print line    # not a nested macro
  145.         else if (sp >= maxsp)
  146.             print ".tm macros nested too deeply (" sp " levels)"
  147.         else {            # nesting
  148.             # stack old one
  149.             sp++
  150.             nleftstack[sp] = nleft
  151.             ptrstack[sp] = ptr
  152.             macrostack[sp] = macro
  153.             nargstack[sp] = nargs
  154.             condstack[sp] = cond
  155.             for (i = 1; i <= nargs; i++)
  156.                 argstack[sp ":" i] = args[i]
  157.  
  158.             # start new one, mostly pulling arguments apart
  159.             macro = cmd
  160.             nleft = macrolen[macro]
  161.             ptr = macros[macro]
  162.             cond = 0
  163.             argno = 1
  164.             pos = length(macro) + 1
  165.             for (;;) {
  166.                 while (substr(line, pos, 1) ~ /[ \t]/)
  167.                     pos++
  168.                 if (pos > length(line))
  169.                     break        # NOTE BREAK OUT
  170.                 arg = ""
  171.                 if (substr(line, pos, 1) == "\"") {
  172.                     pos++
  173.                     while (substr(line, pos, 1) ~ /[^"]/) {
  174.                         arg = arg substr(line, pos, 1)
  175.                         pos++
  176.                     }
  177.                     pos++
  178.                 } else
  179.                     while (substr(line, pos, 1) ~ /[^ \t]/) {
  180.                         arg = arg substr(line, pos, 1)
  181.                         pos++
  182.                     }
  183.                 args[argno++] = arg
  184.             }
  185.             nargs = argno - 1
  186.         }
  187.  
  188.         # clean up any completed macros
  189.         while (nleft <= 0 && sp > 0) {
  190.             nleft = nleftstack[sp]
  191.             ptr = ptrstack[sp]
  192.             macro = macrostack[sp]
  193.             nargs = nargstack[sp]
  194.             cond = condstack[sp]
  195.             for (i = 1; i <= nargs; i++)
  196.                 args[i] = argstack[sp ":" i]
  197.             sp--
  198.         }
  199.  
  200.         # finally, get next line
  201.         if (nleft > 0) {
  202.             line = macrotext[ptr++]
  203.             nleft--
  204.         } else
  205.             line = ""    # signal loop to terminate
  206.     }
  207.  
  208. #    print ".^#", int(NR - nroffset + 1), inname
  209.     print ".^#", NR - nroffset + 1, inname
  210.     next
  211. }
  212. {
  213.     # it's ordinary
  214.     print
  215. }
  216.